home *** CD-ROM | disk | FTP | other *** search
- /*
- File: HandySample.c
-
- Description:
- This file contains the main application program for the HandySample.
- Routines in this file are responsible for handling events directed
- at the application.
-
- Copyright:
- © Copyright 1999 Apple Computer, Inc. All rights reserved.
-
- Disclaimer:
- IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- Change History (most recent first):
- Tue, Jan 18, 2000 -- created
- */
-
-
- #include "HandySample.h"
- #include "HandyWindow.h"
- #include "SampleUtils.h"
-
- #include <Menus.h>
- #include <Windows.h>
- #include <Dialogs.h>
- #include <Events.h>
- #include <Fonts.h>
- #include <SegLoad.h>
- #include <Resources.h>
- #include <Balloons.h>
- #include <Devices.h>
- #include <AppleEvents.h>
- #include <ToolUtils.h>
- #include <Appearance.h>
- #include <Navigation.h>
- #include <StandardFile.h>
- #include <PLStringFuncs.h>
- #include <TextUtils.h>
- #include <ControlDefinitions.h>
- #include <Gestalt.h>
-
-
-
- /* our globals */
-
- Boolean gRunning = true; /* true while the app is running */
- RgnHandle gMouseRgn = NULL; /* the mouse region passed to WaitNextEvent */
- Boolean gIsFrontApp = true; /* true while we're in the forground. */
-
-
-
- /* ResetMenus is called immediately before all calls to
- MenuSelect or MenuKey. In this routine, we re-build
- or enable the menus as appropriate depending on the
- current environment */
- static void ResetMenus(void) {
- Boolean drawnSlowly;
- MenuHandle fileMenu;
- fileMenu = GetMenuHandle(mFile);
- /* here, if the frontmost window is a handy window, then
- enable and check the slow item according to it's slow drawing
- state. Otherwise, disable the item. */
- if ( HandyWindowGetSlow(FrontWindow(), &drawnSlowly) == noErr ) {
- EnableMenuItem(fileMenu, iSlow);
- CheckMenuItem(GetMenuHandle(mFile), iSlow, drawnSlowly);
- } else DisableMenuItem(fileMenu, iSlow);
- }
-
-
- /* DoMenuCommand is called in response to MenuKey
- or MenuSelect. Here, we dispatch the menu command
- to its appropriate handler, or if it's a small action
- we do it here. */
- static void DoMenuCommand(long rawMenuSelectResult) {
- short menu, item;
- /* decode the MenuSelect result */
- menu = (rawMenuSelectResult >> 16);
- if (menu == 0) return;
- item = (rawMenuSelectResult & 0x0000FFFF);
- /* dispatch on result */
- switch (menu) {
- /* apple menu commands */
- case mApple:
- if (item == iAbout) {
- ParamAlert(kAboutBoxAlertID, NULL, NULL);
- }
- break;
-
- /* file menu commands */
- case mFile:
- if (item == iSlow) {
- Boolean drawnSlowly;
- WindowPtr target;
- /* if the frontmost window is a handy window, then
- invert it's slow drawing state. */
- if ( HandyWindowGetSlow((target = FrontWindow()), &drawnSlowly) == noErr ) {
- HandyWindowSetSlow(target, ! drawnSlowly);
- }
- } else if (item == iQuit) {
- gRunning = false;
- }
- break;
-
- }
- /* unhilite the menu bar */
- HiliteMenu(0);
- }
-
-
- /* QuitAppleEventHandler is our quit Apple event handler. this routine
- is called when a quit Apple event is sent to our application. Here,
- we set the gRunning flag to false. NOTE: it is not appropriate to
- call ExitToShell here. Instead, by setting the flag to false we
- fall through the bottom of our main loop the next time we're called. */
- static pascal OSErr QuitAppleEventHandler(const AppleEvent *appleEvt, AppleEvent* reply, unsigned long refcon) {
-
- gRunning = false;
-
- return noErr;
- }
-
-
-
- /* HandleMouseDown is called for mouse down events. The main difference
- over 'the usual' mouse event handler, is we use the grabbing hand
- cursor inside of window drag and resize operations. Other clicks
- are dispatched to routines defined in HandyWindows.h as appropriate. */
- static void HandleMouseDown(EventRecord *ev) {
- WindowPtr theWindow;
- short partcode;
- switch ((partcode = FindWindow(ev->where, &theWindow))) {
- /* inside the window's content area */
- case inContent:
- if (theWindow != FrontWindow()) {
- /* if it's not the frontmost window,
- then make it the frontmost window. */
- SelectWindow(theWindow);
- } else {
- /* otherwise, if it's a rendering window,
- pass the click along to the window. */
- Point where;
- SetPort(GetWindowPort(theWindow));
- where = ev->where;
- GlobalToLocal(&where);
- if (IsHandyWindow(theWindow))
- HandyWindowMouse(theWindow, where, ev->modifiers);
- }
- break;
-
- /* menu bar clicks */
- case inMenuBar:
- SetThemeCursor(kThemePointingHandCursor);
- ResetMenus();
- DoMenuCommand(MenuSelect(ev->where));
- break;
-
- /* track clicks in the close box */
- case inGoAway:
- if (TrackGoAway(theWindow, ev->where)) {
- if (IsHandyWindow(theWindow)) {
- HandyWindowCloseWindow(theWindow);
- gRunning = false;
- }
- }
- break;
-
- /* allow window drags */
- case inDrag:
- { Rect boundsRect = {0,0, 32000, 32000};
- SetThemeCursor(kThemeClosedHandCursor);
- DragWindow(theWindow, ev->where, &boundsRect);
- }
- break;
-
- /* allow window drags */
- case inGrow:
- { Rect sizerect;
- long grow_result;
- SetThemeCursor(kThemeClosedHandCursor);
- if (GetHandyWindowGrowLimits(theWindow, &sizerect) != noErr)
- SetRect(&sizerect, 300, 150, 32767, 32767);
- grow_result = GrowWindow(theWindow, ev->where, &sizerect);
- if (grow_result != 0) {
- SizeWindow(theWindow, LoWord(grow_result), HiWord(grow_result), true);
- if (IsHandyWindow(theWindow))
- HandyWindowSizeChanged(theWindow);
- }
- }
- break;
-
- /* zoom box clicks. NOTE: since the rendering window
- always sets the standard rectangle to the 'best size' for
- displaying the current HTML window, the inZoomOut partcode
- will zoom the window to that size rather than the entire screen.*/
- case inZoomIn:
- case inZoomOut:
- if (TrackBox(theWindow, ev->where, partcode)) {
- Rect r;
- CGrafPtr gp;
- gp = GetWindowPort(theWindow);
- GetPortBounds(gp, &r);
- SetPort(gp);
- EraseRect(&r);
- ZoomWindow(theWindow, partcode, true);
- if (IsHandyWindow(theWindow))
- HandyWindowSizeChanged(theWindow);
- }
- break;
-
- }
- }
-
-
- /* ResetCursor sets the cursor according to the location of the mouse on
- the screen. If the mouse is inside of a handy window, then the task of
- setting the cursor is passed along to the HandyWindowCursor routine
- defined in HandyWindows.c. */
- static void ResetCursor(EventRecord *ev) {
- WindowPtr target;
- Point where;
- short partcode;
- /* discover the mouse's location */
- switch ((partcode = FindWindow(ev->where, &target))) {
- /* if it's in the content area of a window, then we either
- set the cursor to an arrow (if it's not the front window) or
- we ask HandyWindowCursor to set the cursor. */
- case inContent:
- if (target != FrontWindow()) {
- SetThemeCursor(kThemeArrowCursor);
- SetEmptyRgn(gMouseRgn);
- } else {
- SetPort(GetWindowPort(target));
- where = ev->where;
- GlobalToLocal(&where);
- if ( ! HandyWindowCursor( target, where, ev->modifiers, gMouseRgn) ) {
- SetThemeCursor(kThemeArrowCursor);
- SetEmptyRgn(gMouseRgn);
- }
- }
- break;
-
- /* the following sets the cursor according to other locations
- in the gui, setting the mouse region to reflect the region where
- the cursor should remain as set. */
- case inMenuBar:
- SetThemeCursor(kThemePointingHandCursor);
- GetMenuBarRegion(gMouseRgn);
- break;
- case inCollapseBox:
- SetThemeCursor(kThemePointingHandCursor);
- GetWindowRegion(target, kWindowCollapseBoxRgn, gMouseRgn);
- break;
- case inZoomIn:
- case inZoomOut:
- SetThemeCursor(kThemePointingHandCursor);
- GetWindowRegion(target, kWindowZoomBoxRgn, gMouseRgn);
- break;
- case inGoAway:
- SetThemeCursor(kThemePointingHandCursor);
- GetWindowRegion(target, kWindowCloseBoxRgn, gMouseRgn);
- break;
- case inGrow:
- SetThemeCursor(kThemeOpenHandCursor);
- GetWindowRegion(target, kWindowGrowRgn, gMouseRgn);
- break;
- case inDrag:
- SetThemeCursor(kThemeOpenHandCursor);
- GetWindowRegion(target, kWindowDragRgn, gMouseRgn);
- break;
- default:
- SetThemeCursor(kThemeArrowCursor);
- SetEmptyRgn(gMouseRgn);
- break;
- }
- }
-
-
-
-
-
- /* HandleEvent is the main event handling routine for the
- application. ev points to an event record returned by
- WaitNextEvent. */
- void HandleEvent(EventRecord *ev) {
- WindowPtr target;
-
- /* process other event types */
- switch (ev->what) {
- case keyDown:
- case autoKey:
- if ((ev->modifiers & cmdKey) != 0) {
- ResetMenus();
- DoMenuCommand(MenuKey((char) (ev->message & charCodeMask)));
- ev->what = nullEvent;
- } else {
- target = FrontWindow();
- if (IsHandyWindow(target))
- HandyWindowKey(target, (char) (ev->message & charCodeMask), ev->modifiers);
- }
- break;
-
- /* for null events, track the cursor. */
- case nullEvent:
- if (gIsFrontApp)
- ResetCursor(ev);
- break;
-
- case osEvt:
- if (((ev->message >> 24) & 255) == mouseMovedMessage) {
- if (gIsFrontApp)
- ResetCursor(ev);
- } else if (((ev->message >> 24) & 255) == suspendResumeMessage) {
- Boolean switchingIn;
- switchingIn = ((ev->message & resumeFlag) != 0);
- /* reset the cursor to its last known state */
- gIsFrontApp = switchingIn;
- /* send an activate event to the frontmost window */
- target = FrontWindow();
- if (IsHandyWindow(target))
- HandyWindowActivate(target, gIsFrontApp);
- }
- break;
-
- /* for activate events we call the window's activate event
- handler. */
- case activateEvt:
- target = (WindowPtr) ev->message;
- if (IsHandyWindow(target))
- HandyWindowActivate(target, ((ev->modifiers&1) != 0));
- break;
-
- /* for update events we call the window's update event
- handler. As we may be called from inside of a dialog filter
- routine, if the window not a handy window then we ignore the
- update event. */
- case updateEvt:
- target = (WindowPtr) ev->message;
- if (IsHandyWindow(target))
- HandyWindowUpdate(target);
- break;
-
- /* for mouse events we call the the HandleMouseDown routine
- defined above. */
- case mouseDown:
- HandleMouseDown(ev);
- break;
-
- /* Apple events. */
- case kHighLevelEvent:
- AEProcessAppleEvent(ev);
- break;
- }
- }
-
-
-
-
- /* MyIdleInteractProc is the idle procedure called by AEInteractWithUser while we are waiting
- for the application to be pulled into the forground. It simply passes the event along
- to HandleNextEvent */
- static pascal Boolean MyIdleInteractProc(EventRecord *theEvent, long *sleepTime, RgnHandle *mouseRgn) {
- HandleEvent(theEvent);
- return ( ! gRunning ); /* quit waiting if we're not running */
- }
-
-
-
-
- /* ascii codes we respond to in our filter routine */
- enum {
- ETX = 3, /* ENTER KEY */
- CR = 13 /* RETURN KEY */
- };
-
- /* MyModalFilterProc is the modal filter routine we call while alerts are
- being displayed. Its main purpose is to ensure our activation and update
- routines are called appropriately for other windows displayed in our
- application. */
- static pascal Boolean MyModalFilterProc(DialogPtr theDialog, EventRecord *theEvent, DialogItemIndex *itemHit) {
- switch (theEvent->what) {
- case keyDown:
- case autoKey:
- { char key;
- key = (char) (theEvent->message & charCodeMask);
- if (key == ETX || key == CR) {
- *itemHit = ok;
- return true;
- }
- }
- break;
- case nullEvent:
- case osEvt:
- case activateEvt:
- case kHighLevelEvent:
- case updateEvt:
- HandleEvent(theEvent);
- break;
- }
- return false;
- }
-
-
- /* ParamAlert is a general alert handling routine. If Apple events exist, then it
- calls AEInteractWithUser to ensure the application is in the forground, and then
- it displays an alert after passing the s1 and s2 parameters to ParamText. */
- short ParamAlert(short alertID, StringPtr s1, StringPtr s2) {
- AEIdleUPP aeIdleProc;
- ModalFilterUPP filterProc;
- OSStatus err;
- filterProc = NULL;
- aeIdleProc = NULL;
- aeIdleProc = NewAEIdleUPP(MyIdleInteractProc);
- if (aeIdleProc == NULL) { err = memFullErr; goto bail; }
- filterProc = NewModalFilterUPP(MyModalFilterProc);
- if (filterProc == NULL) { err = memFullErr; goto bail; }
- err = AEInteractWithUser(kNoTimeOut, NULL, aeIdleProc);
- if (err != noErr) goto bail;
- ParamText(s1, s2, NULL, NULL);
- err = Alert(alertID, filterProc);
- DisposeAEIdleUPP(aeIdleProc);
- DisposeModalFilterUPP(filterProc);
- return err;
- bail:
- if (aeIdleProc != NULL) DisposeAEIdleUPP(aeIdleProc);
- if (filterProc != NULL) DisposeModalFilterUPP(filterProc);
- return err;
- }
-
-
-
-
-
-
-
-
- /* the main program */
-
- int main(void) {
- /* allocate the mouse region. We pass this region to
- WaitNextEvent after setting the cursor so we can
- receive mouse moved events. */
- gMouseRgn = NewRgn();
-
- /* say hello to the appearance manager */
- RegisterAppearanceClient();
-
- /* set the cursor to a handy one... */
- SetThemeCursor(kThemePointingHandCursor);
-
- /* install our event handlers */
- AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(QuitAppleEventHandler), 0, false);
-
- /* set up the menu bar */
- SetMenuBar(GetNewMBar(kMacOS9MenuBarID));
- DrawMenuBar();
-
- /* open some handy windows */
- OpenHandyWindow(kHandyWindowTwo, true);
- OpenHandyWindow(kHandyWindowOne, false);
-
- /* run the app */
- while (gRunning) {
- EventRecord ev;
- RgnHandle theMouseRgn;
- /* if the mouse region is empty, then we'll pass NULL to WaitNextEvent. */
- if (EmptyRgn(gMouseRgn)) theMouseRgn = NULL; else theMouseRgn = gMouseRgn;
- /* get the next event */
- if ( ! WaitNextEvent(everyEvent, &ev, GetCaretTime(), theMouseRgn) )
- ev.what = nullEvent;
- /* call our handler to deal with it. */
- HandleEvent(&ev);
-
- }
-
- /* close all of our windows. */
- CloseAllHandyWindows();
- /* close down and leave. */
- UnregisterAppearanceClient();
- DisposeRgn(gMouseRgn);
- ExitToShell();
- return 0;
- }